﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
//using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
//using Microsoft.SqlServer.Dts.Runtime;

/// TODO: need to add msxml6.dll as self reg component

namespace Workflows.Components.TextMining.Collapse
{
    /// <summary>
    /// 
    /// </summary>
    //public class FuzzyGroupingWorker:IWorker
    //{
    //    #region fields
    //    private Guid _TicketID;
    //    private Thread _WorkerThread;
    //    private RunContext _Context;
    //    private FuzzyGroupingInstruction _Instruction;
    //    private FuzzyGroupingOutput _Output;
    //    #endregion

    //    #region IWorker Members

    //    public Thread WorkerThread
    //    {
    //        get { return this._WorkerThread; }
    //    }

    //    public InstructionBase Instruction
    //    {
    //        get
    //        {
    //            return this._Instruction;
    //        }
    //    }

    //    public ResultBase Output
    //    {
    //        get {
    //            return this._Output;
    //        }
    //    }

    //    public Type ComponentType
    //    {
    //        get
    //        {
    //            return typeof (FuzzyGroupingComponent);
    //        }
    //    }

    //    public RunContext Context
    //    {
    //        get
    //        {
    //            return this._Context;
    //        }
    //        set { this._Context = value; }
    //    }

    //    public void SetInstruction(Guid ticketGuid, InstructionBase request)
    //    {
    //        this._TicketID = ticketGuid;
    //        this._Instruction = (FuzzyGroupingInstruction) request;
    //    }

    //    public void SetInstruction(RunContext context, Guid ticketGuid, InstructionBase request)
    //    {
    //        this._TicketID = ticketGuid;
    //        this._Instruction = (FuzzyGroupingInstruction)request;
    //        this._Context = context;
    //    }

    //    public void DoWork()
    //    {
    //        if(this.WorkerStartedEvent !=null)
    //        {
    //            this.WorkerStartedEvent(this._TicketID, this, this.GetType(), this._Instruction);
    //        }
    //        this._WorkerThread = Thread.CurrentThread;
    //        this.RunFuzzyGrouping();
    //    }

    //    public void DoWorkAsync()
    //    {
    //        if (this.WorkerStartedEvent != null)
    //        {
    //            this.WorkerStartedEvent(this._TicketID, this, this.GetType(), this._Instruction);
    //        }
    //        this._WorkerThread = new Thread(new ThreadStart(this.RunFuzzyGrouping));
    //        this._WorkerThread.Start();
    //    }

    //    public void CancelWork()
    //    {
    //        if(this._WorkerThread !=null && this._WorkerThread.IsAlive)
    //        {
    //            this._WorkerThread.Abort();

    //            if(this.WorkerCancelledEvent!=null)
    //            {
    //                this.WorkerCancelledEvent(this._TicketID, this.GetType(), this._Instruction);
    //            }
    //        }
    //    }

    //    public event WorkerStarted WorkerStartedEvent;
    //    public event WorkerFinished WorkerFinishedEvent;
    //    public event WorkerHasError WorkerErredEvent;
    //    public event WorkerCancelled WorkerCancelledEvent;
    //    public event WorkerStatusChanged WorkerStatusChangedEvent;

    //    #endregion

    //    //#region test
    //    //public string Test()
    //    //{
            
    //    //}
    //    //#endregion

    //    #region work
    //    private void RunFuzzyGrouping()
    //    {
    //        try
    //        {
    //            string selectSql = string.Format("select {0},{1} from {2}", this._Instruction.IDFieldName,
    //                                             this._Instruction.FieldName, this._Instruction.TableName);
    //            TableColumn[] cols = DbUtil.GetTableColumns(DataProviderType.MSSQL, this._Instruction.ConnStr, selectSql);
    //            List<TableColumn> tgtCols=new List<TableColumn>();
    //            tgtCols.AddRange(cols);
    //            TableColumn keyInCol=new TableColumn();
    //            keyInCol.AllowNull = false;
    //            keyInCol.ColumnName = "_Key_In";
    //            keyInCol.DbType = SqlDbType.Int;
    //            keyInCol.IsFK = false;
    //            keyInCol.IsIndexed = false;
    //            keyInCol.IsIdentity = false;
    //            keyInCol.IsPK = false;
    //            keyInCol.Ordinal = 2;
    //            keyInCol.Precision = 0;
    //            keyInCol.Scale = 0;
    //            keyInCol.Size = 0;
    //            tgtCols.Add(keyInCol);
    //            TableColumn keyOutCol = new TableColumn();
    //            keyOutCol.AllowNull = false;
    //            keyOutCol.ColumnName = "_Key_Out";
    //            keyOutCol.DbType = SqlDbType.Int;
    //            keyOutCol.IsFK = false;
    //            keyOutCol.IsIndexed = false;
    //            keyOutCol.IsIdentity = false;
    //            keyOutCol.IsPK = false;
    //            keyOutCol.Ordinal = 3;
    //            keyOutCol.Precision = 0;
    //            keyOutCol.Scale = 0;
    //            keyOutCol.Size = 0;
    //            tgtCols.Add(keyOutCol);
    //            TableColumn scoreCol = new TableColumn();
    //            scoreCol.AllowNull = false;
    //            scoreCol.ColumnName = "_Score";
    //            scoreCol.DbType = SqlDbType.Real;
    //            scoreCol.IsFK = false;
    //            scoreCol.IsIndexed = false;
    //            scoreCol.IsIdentity = false;
    //            scoreCol.IsPK = false;
    //            scoreCol.Ordinal = 4;
    //            scoreCol.Precision = 0;
    //            scoreCol.Scale = 0;
    //            scoreCol.Size = 0;
    //            tgtCols.Add(scoreCol);

    //            TableHelper.CreateTable(this._Instruction.ConnStr, this._Instruction.OutputTableName, tgtCols.ToArray(),
    //                                    true);


    //            string appFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
    //            appFolder = Path.Combine(appFolder, "Workflow Design");
    //            if (!Directory.Exists(appFolder))
    //            {
    //                Directory.CreateDirectory(appFolder);
    //            }
    //            appFolder = Path.Combine(appFolder, "SSIS packages");
    //            if(!Directory.Exists(appFolder))
    //            {
    //                Directory.CreateDirectory(appFolder);
    //            }
    //            string ssisPkgFilePath = Path.Combine(appFolder,
    //                                                  "FuzzyGrouping_" + this._Instruction.OwnerComponentID.ToString() +
    //                                                  ".dtsx");
    //            if(File.Exists(ssisPkgFilePath))
    //            {
    //                File.Delete(ssisPkgFilePath);
    //            }
    //            string assemblyFilePath = Assembly.GetExecutingAssembly().Location;
    //            string binFolderPath = Path.GetDirectoryName(assemblyFilePath);
    //            string collapseFolderPath = Path.Combine(binFolderPath, "Collapse");
    //            string originalDtsxPkgFilePath = Path.Combine(collapseFolderPath, "Package.dtsx");

    //            this.GenerateSsisPackageForFuzzyGrouping(originalDtsxPkgFilePath, ssisPkgFilePath);
    //            if(!File.Exists(ssisPkgFilePath))
    //            {
    //                throw new Exception("Unable to create SSIS package for fuzzy lookup");
    //            }

    //            Application app=new Application();
    //            Package pkg = app.LoadPackage(ssisPkgFilePath, null);
    //            DTSExecResult result = pkg.Execute();
    //            if (result != DTSExecResult.Success)
    //            {
    //                throw new Exception("Fuzzy grouping SSIS package failed");
    //            }

    //            Dictionary<int,double> id_Scores=new Dictionary<int, double>();
    //            Dictionary<int,int> id_CollapsedIDs=new Dictionary<int, int>();
    //            List<int> collapsedIDs=new List<int>();
    //            SqlConnection conn=new SqlConnection(this._Instruction.ConnStr);
    //            try
    //            {
    //                conn.Open();
    //                SqlCommand cmd = conn.CreateCommand();
    //                cmd.CommandText = string.Format("select {0},{1},{2} from {3}", this._Instruction.IDFieldName,
    //                                                "_Key_Out", "_Score", this._Instruction.OutputTableName);
    //                SqlDataReader reader = cmd.ExecuteReader();
    //                while(reader.Read())
    //                {
    //                    int pk = int.Parse(reader[this._Instruction.IDFieldName].ToString());
    //                    int collapsedID = int.Parse(reader["_Key_Out"].ToString());
    //                    double score = double.Parse(reader["_Score"].ToString());
    //                    id_Scores.Add(pk,score);
    //                    id_CollapsedIDs.Add(pk,collapsedID);
    //                    if(!collapsedIDs.Contains(collapsedID))
    //                    {
    //                        collapsedIDs.Add(collapsedID);
    //                    }
    //                }
    //                reader.Close();
    //            }
    //            catch(Exception ex1)
    //            {
    //                if (this.WorkerErredEvent != null)
    //                {
    //                    this.WorkerErredEvent(this._TicketID, this.GetType(), this._Instruction, ex1.ToString());
    //                }
    //            }
    //            finally
    //            {
    //                conn.Close();
    //            }

    //            this._Output = new FuzzyGroupingOutput(this._Instruction.OwnerComponentID, this._TicketID,
    //                                                   id_CollapsedIDs, id_Scores, collapsedIDs.Count);
    //            if(this.WorkerFinishedEvent !=null)
    //            {
    //                this.WorkerFinishedEvent(this._TicketID, this.GetType(), this._Instruction, this._Output);
    //            }
    //        }
    //        catch(Exception ex)
    //        {
    //            if(this.WorkerErredEvent !=null)
    //            {
    //                this.WorkerErredEvent(this._TicketID, this.GetType(), this._Instruction, ex.ToString());
    //            }
    //        }
    //    }

    //    private void GenerateSsisPackageForFuzzyGrouping(string srcDtsxPkgFilePath, string dtsxPkgFilePath)
    //    {
    //        try
    //        {
    //            Application app = new Application();
    //            Package dtsPkg = app.LoadPackage(srcDtsxPkgFilePath, null);

    //            // set connection 
    //            ConnectionManager connMgr = dtsPkg.Connections[0];
    //            connMgr.ConnectionString = this._Instruction.ConnStr;
                

    //            // identify 3 components 
    //            IDTSComponentMetaData90 dataSourceComponent = null;
    //            IDTSComponentMetaData90 fuzzyGroupComponent = null;
    //            IDTSComponentMetaData90 destinationComponent = null;
    //            Executables execs = dtsPkg.Executables;
    //            foreach(Executable exe in execs)
    //            {
    //                TaskHost taskHost = (TaskHost)exe;
    //                if(taskHost.InnerObject is MainPipe)
    //                {
    //                    MainPipe dataFlowTask = (MainPipe) taskHost.InnerObject;
    //                    foreach (IDTSComponentMetaData90 component in dataFlowTask.ComponentMetaDataCollection)
    //                    {


    //                        if (component.Name == "OLE DB Source")
    //                        {
    //                            dataSourceComponent = component;
    //                        }
    //                        if (component.Name == "Fuzzy Grouping")
    //                        {
    //                            fuzzyGroupComponent = component;
    //                        }
    //                        if (component.Name == "OLE DB Destination")
    //                        {
    //                            destinationComponent = component;
    //                        }
    //                    }
    //                }
    //            }
               
    //            // data source, update selectsql
    //            CManagedComponentWrapper instance1 = dataSourceComponent.Instantiate();
    //            instance1.ProvideComponentProperties();
    //            instance1.SetComponentProperty("AccessMode", 2);    // Sql Command
    //            instance1.SetComponentProperty("SqlCommand",
    //                                           string.Format("select {0} as KeyField, {1} as LookupField from {2}", this._Instruction.IDFieldName,
    //                                                         this._Instruction.FieldName, this._Instruction.TableName));
    //            // reinitialize the metadata
    //            //instance1.AcquireConnections(null);
    //            //instance1.ReinitializeMetaData();
    //            //instance1.ReleaseConnections();

    //            // Fuzzy Grouping set min similarity
    //            CManagedComponentWrapper instance2 = fuzzyGroupComponent.Instantiate();
    //            instance2.ProvideComponentProperties();
    //            instance2.SetComponentProperty("MinSimilarity", this._Instruction.SimilarityThreshold);

    //            // OLEDB Destination component, set table name
    //            CManagedComponentWrapper instance3 = destinationComponent.Instantiate();
    //            instance3.ProvideComponentProperties();
    //            instance3.SetComponentProperty("OpenRowset", this._Instruction.OutputTableName);
                
    //            // save package as a copy
    //            app.SaveToXml(dtsxPkgFilePath, dtsPkg, null);
    //            //string xml = null;
    //            //dtsPkg.SaveToXML(out xml, null);
    //            //XmlDocument xDoc=new XmlDocument();
    //            //xDoc.LoadXml(xml);
    //            //xDoc.Save(dtsxPkgFilePath);
    //        }
    //        catch (Exception ex)
    //        {
    //            if (this.WorkerErredEvent != null)
    //            {
    //                this.WorkerErredEvent(this._TicketID, this.GetType(), this._Instruction, ex.ToString());
    //            }
    //        }
    //    }
    //    #endregion
    //}
}
